<template>
  <div
    class="form-richtext"
    v-if="defaultConfig"
    :class="[
      readonly ? 'form-readonly' : 'form-toedit',
      showUp ? 'show-all' : 'show-hide',
    ]"
    v-loading="loading"
  >
    <!-- <div v-if="readonly && value" class="link-text" @click="showUp = !showUp">
      {{ showUp ? '收起' : '展开' }}
    </div> -->
    <el-button ref="joker" class="form-richtext-blur-vdom"></el-button>
    <Editor
      api-key="tzpj2689eva6ekxd4o4myukvl2tg9h2xujojce0jd6tlg8pn"
      ref="Editor"
      :disabled="disabled"
      v-if="!readonly"
      v-model="valueRender"
      :init="defaultConfig"
      :placeholder="placeholder"
      @onClick="editorClick"
    />
    <div
      v-if="readonly"
      class="tox-tinymce richtext-view"
      v-html="valueRender"
      @click="editorClick"
    ></div>
  </div>
</template>

<script>
import FormMixin from '@src/component/form/mixin/form';
import defaultConfig from './config';
import * as _ from 'lodash';
import Uploader from '@src/util/uploader';
import Editor from '@tinymce/tinymce-vue';
const imgRge = /(data:image)|\.(png|bmp|gif|jpg|jpeg|tiff|image)$/i;
import i18n from '@src/locales'

export default {
  name: 'form-richtext',
  mixins: [FormMixin],
  components: {
    Editor,
  },
  props: {
    value: {
      type: String,
      default: '',
    },
    readonly: {
      type: Boolean,
      default: false,
    },
    showUp: {
      type: Boolean,
      default: true,
    },
    maxLength: {
      type: Number
    },
    hiddenBoldEnable: {
      type: Boolean,
      default: false,
    }
  },
  computed: {
    valueRender: {
      get() {
        return this.value.replaceAll('src="../../files/auth/get', `src="${window.location.origin}/files/auth/get`);
      },
      set(value) {
        this.debounceInputForValue(value)
      },
    },
  },
  data() {
    return {
      defaultConfig: null,
      loading: false,
      // showUp: true,
      clickTimeout: null,
      clickCount: 0
    };
  },
  mounted() {
    // 判断当前语言环境
    let laEnv = i18n.locale;
    let defaultConfig_ = defaultConfig();
    if(laEnv !== 'zh'){
      defaultConfig_['language'] = laEnv;
      defaultConfig_['language_url'] = '';
    }
    defaultConfig_['images_upload_handler'] = this.uploadImage;
    defaultConfig_['init_instance_callback'] = this.editorMounted;
    defaultConfig_['file_picker_callback'] = this.filePickUp;
    defaultConfig_["images_dataimg_filter"] = this.imagesDataimgFilter;
    if (this.readonly) {
      defaultConfig_['toolbar'] = false;
    }
    if(this.hiddenBoldEnable) {
      defaultConfig_['toolbar'] = 'fontselect fontsizeselect forecolor backcolor image media fullscreen | formatselect alignleft aligncenter alignright alignjustify outdent indent italic underline strikethrough link | ';
    }
    this.$nextTick(() => {
      this.$set(this, 'defaultConfig', defaultConfig_);
    }, 500);
  },
  beforeDestroy() {
    console.log('beforeDestroy');
  },
  methods: {
    getContent() {
      const editor = this.$refs.Editor.editor;
      return editor.getContent({
        format: 'text'
      });
    },
    editorMounted() {},
    // inputValue: _.debounce(function (e) {
    //   this.inputForValue(this.valueRender);
    // }, 500),
    uploadImage(blobInfo, success, failure) {
      console.log(blobInfo, 'blobInfo');
      console.log(blobInfo.base64());
      console.log(blobInfo.blob());
      let blob_ = blobInfo.blob();
      if (!Reflect.has(blob_, 'name')) {
        return;
      }
      Uploader.batchUploadWithParse({
        files: [blobInfo.blob()],
        action: '/files/upload',
      }).then((result = {}) => {
        console.log(result, 'result');
        try {
          let { success: successUrl } = result;
          if (!successUrl.length) throw '上传失败';
          success(successUrl[0].url);
        } catch (error) {
          console.warn(error, 'error try catch');
          failure(error);
        }
      });
    },
    filePickUp(cb, value, meta) {
      console.log(value, 'value');
      // TO DO 根据需要上传的东西控制上传类型
      console.log(meta, 'meta');
      // const filetypeEnum = {
      //   image: () => {},
      // };
      try {
        this.$fast.upload
          .upload({
            multiple: false,
          })
          .then(result => {
            console.log(result, 'result');
            try {
              let { data: successUrl } = result;
              if (!successUrl.length) throw '上传失败';
              cb(successUrl[0].url);
            } catch (error) {
              console.warn(error, 'error try catch');
            }
          });
      } catch (error) {
        console.warn(error, 'error try catch');
      }
    },
    setValueRenderHandler(value) {
      const element = document.createElement('div');
      element.innerHTML = value;
      
      this.processBase64Images(element, value);
    },
    async processBase64Images(element, value) {
      
      const richTextDiv = element;
      const images = richTextDiv.querySelectorAll('img');
      const uploadPromises = [];

      images.forEach(img => {
        
        const src = img.src;
        
        // if (src.startsWith('data:image')) {
        //   uploadPromises.push(this.uploadBase64Image(src));
        // }
        
        // 如果 src 是 blob:https:// 开头的，也需要上传
        if (src.startsWith('blob:https://')) {
          uploadPromises.push(this.uploadBase64Image(src));
        }
        
      })
      
      if (uploadPromises.length === 0) {
        this.inputForValue(value);
        return;
      }

      try {
        
        const urls = await Promise.all(uploadPromises);
        let urlIndex = 0;

        images.forEach(img => {
          
          const src = img.src;
          
          // if (src.startsWith('data:image')) {
          //   img.src = urls[urlIndex];
          //   urlIndex++
          // }
          
          if (src.startsWith('blob:https://')) {
            img.src = urls[urlIndex];
            urlIndex++
          }
          
        })
        
        const newValue = richTextDiv.innerHTML;
        this.inputForValue(newValue);
        
      } catch (error) {
        console.error('Error uploading images:', error);
      }
    },
    base64ToFile(base64, filename) {
      const arr = base64.split(',');
      const mime = arr[0].match(/:(.*?);/)[1];
      const bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], filename, { type: mime });
    },
    async uploadBase64Image(src) {
      
      console.log('uploadBase64Image src', src);
      
      let file = {}
      
      // 将 base64 转换为 File 对象
      if (src.includes('data:image')) {
        file = this.base64ToFile(src, 'image.png');
      } 
      else if (src.includes('blob:https://')) {
        const response = await fetch(src);
        const blob = await response.blob();
        file = new File([blob], 'image.png', { type: blob.type });
      }
      
      const params = {
        files: [file],
        action: '/files/upload',
      }
      
      return (
        Uploader.batchUploadWithParse(params).then(result => {
          
          console.log(result, 'result');
          
          try {
            
            let { success: successUrl } = result;
            
            const url = successUrl?.[0].url || src
            
            return url;
            
          } catch (error) {
            console.warn(error);
            return src;
          }
          
        })
      
      )
    },
    debounceInputForValue: _.debounce(function (value) {
      this.setValueRenderHandler(value);
    }, 500),
    /**
     * @des 富文本内的点击事件
     */
    editorClick(...args) {
      try {
        if (this.clickTimeout) this.clickTimeout = null;
        this.clickCount++;
        this.clickTimeout = setTimeout(() => {
          this.clickCount = 0;
        }, 500);
        if (this.clickCount < 2) return;
        this.$refs.joker.$el.focus();
        console.log(args, "args");
        let event = args[0];
        let nodeName = event?.target?.nodeName.toLowerCase() || '';
        console.log(event, nodeName, 'editorClick');
        if (event && event.stopPropagation) {
          event.stopPropagation();
        }
        let enum_ = ['a', 'video', 'img'];
        if (!enum_.includes(nodeName))
          return console.warn('editorClick not allow click');
        let src = event?.target?.currentSrc || event?.target?.href || '';
        if (nodeName == 'a') {
          event.target.currentSrc = src;
          event.target.href = 'javascript:void(0)';
          return this.$platform.openLink(src);
        }
        this.handlePreviewFile({
          id: 'richttext-view-file',
          url: src,
          fileName: '预览',
          fileSize: 0,
        });
      } catch (error) {
        console.warn('editorClick try catch error', error);
      }
    },
    /**
     * @des 预览文件
     * 查看附件组件 src/component/common/BaseFileItem/BaseFileItem.vue
     */
    handlePreviewFile(file) {
      const { fileSize, filename, id, url } = file;
      // const downloadUrl = this.genDownloadUrl(file)
      let previewFile = {
        id,
        url,
        fileSize,
        fileName: filename,
        name: filename,
        // downloadUrl,
        fileType: '',
      };
      let icon = this.icon(file);
      switch (icon) {
        case 'img':
        case 'small-img':
          previewFile.fileType = 'image';
          break;
        case 'pdf-file-icon':
        case 'small-pdf-file-icon':
          previewFile.fileType = 'pdf';
          break;
        case 'voice-file-icon':
        case 'small-voice-file-icon':
          previewFile.fileType = 'audio';
          break;
        case 'video-file-icon':
        case 'small-video-file-icon':
          previewFile.fileType = 'video';
          break;
        default:
          previewFile.fileType = '';
          break;
      }
      switch (previewFile.fileType) {
        //视频查看
        case 'video': {
          this.$previewVideo(previewFile.url, previewFile);
          break;
        }

        //图片查看
        case 'image': {
          this.$previewElementImg(previewFile.url, []);
          break;
        }

        // PDF查看
        case 'pdf': {
          this.$previewPDF(previewFile.url, previewFile);
          break;
        }
        default: {
          let a = document.createElement('a');
          a.href = url;
          a.download = previewFile.fileName;
          a.click();
          window.URL.revokeObjectURL(a);
        }
      }

      // this.$refs.bizPreviewFileDialog.open()
    },
    /**
     * @des 文件icon
     * 查看附件组件 src/component/common/BaseFileItem/BaseFileItem.vue
     */
    icon(file) {
      let icon = '';
      const name = file.filename || file.url;

      if (imgRge.test(name)) {
        icon = 'img';
      } else if (/\.(ppt|pptx)$/i.test(name)) {
        icon = 'ppt-file-icon';
      } else if (/\.(mp3)$/i.test(name)) {
        icon = 'voice-file-icon';
      } else if (/\.(mp4)$/i.test(name)) {
        icon = 'video-file-icon';
      } else if (/\.(zip)$/i.test(name)) {
        icon = 'zip-file-icon';
      } else if (/\.(pdf)$/i.test(name)) {
        icon = 'pdf-file-icon';
      } else if (/\.(xls|xlsx)$/i.test(name)) {
        icon = 'xls-file-icon';
      } else if (/\.(doc|docx)$/i.test(name)) {
        icon = 'doc-file-icon';
      } else if (/\.(txt)$/i.test(name)) {
        icon = 'txt-file-icon';
      } else {
        icon = 'other-file-icon';
      }

      if (this.size === 'small') {
        icon = `small-${icon}`;
      }

      return icon;
    },
    imagesDataimgFilter(img) {
      return img.hasAttribute('internal-blob');
    },
  },
};
</script>
<style lang="scss">
@import './index.scss';
.mce-content-body {
  img {
    max-width: 100% !important;
    object-fit: contain;
    height:auto;
  }
  div{
    max-width:100%!important;
    box-sizing:border-box;
    white-space:inherit !important;
  }
  span{
    white-space:inherit !important;
  }
  p{
    white-space:inherit !important;
  }
}
.richtext-view {
  // padding: 0px;
  padding-top: 4px;
  width:100%;
  overflow-x:hidden;
  img {
    max-width: 100% !important;
    object-fit: contain;
    height:auto;
  }
  div{
    max-width:100%!important;
    box-sizing:border-box;
    white-space:inherit !important;
  }
  span{
    white-space:inherit !important;
  }
  p{
    white-space:inherit !important;
  }
}
</style>
